This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.


library(rstan)
library(bayesplot)
library(sp)
data(meuse)
library('plotly')
library(lattice)
source("~/Documents/BU_2019_Fall/bslm.R")
compute_distances <- function(x,y){
  n<- length(x)
  D = matrix(0,nrow=n,ncol=n)
  for(i in 1:n){
    for(j in 1:n){
        p1 = c(x[i],y[i])
        p2 = c(x[j],y[j])
        D[i,j] <- sqrt(sum((p1 - p2)^2))
    }
  }
  return(D)
}

D <- compute_distances(meuse$x,meuse$y)
p <- plot_ly(z=~D)
layout(p,title = "Distances Between Sites", xaxis=list(title = 'Site'),yaxis=list(title = 'Site'))
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap

p<-plot_ly(x= meuse$x,y=meuse$y,z = ~log(meuse$lead))
layout(p,title = "Log lead concentration as a function of location", scene = list(xaxis=list(title = 'x location'),yaxis=list(title = 'y location'),zaxis=list(title = 'Log lead')))
No trace type specified:
  Based on info supplied, a 'scatter3d' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter3d
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
No trace type specified:
  Based on info supplied, a 'scatter3d' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter3d
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode

Fix tau2 to be 1 to understand impact of phi.


phi=1
H <- 1*exp(-D/phi)
p <- plot_ly(z=~H)
layout(p,title = "Spatial Correlation for Phi = 1", xaxis=list(title = 'Site'),yaxis=list(title = 'Site'))
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap

phi=300
H <- 1*exp(D/phi)
p <- plot_ly(z=~H)
layout(p,title = "Spatial Correlation for Phi = 300", xaxis=list(title = 'Site'),yaxis=list(title = 'Site'))
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap

phi=3000
H <- 1*exp(-D/phi)
p <- plot_ly(z=~H)
layout(p,title = "Spatial Correlation for Phi = 3000", xaxis=list(title = 'Site'),yaxis=list(title = 'Site'))
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap
No trace type specified:
  Based on info supplied, a 'heatmap' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#heatmap

xyplot(log(lead) ~ dist.m | soil, data = meuse,
       panel = function(...) {
         panel.xyplot(type = "p", ...)
         panel.lmline(lty = 2, ...)
       })

xyplot(log(lead) ~ dist.m , data = meuse,
       panel = function(...) {
         panel.xyplot(type = "p", ...)
         panel.lmline(lty = 2, ...)
       })

Set up design matrices

y <- log(meuse$lead)
X <- model.matrix(~ -1 + soil + soil:dist.m, data = meuse)

J <- length(levels(meuse$soil))
n <- nrow(X)
p <- ncol(X) / J
site_j <- aggregate(. ~ soil, data = meuse, length)
soil_site <- data.frame(group = site_j$soil,
                             coef = c(rep("_intercept", J), rep("_distance", J)))
X_beta <- model.matrix(~ -1 + coef , data = soil_site)

Metropolis-Gibbs sampling procedure

nchains <- 4
nsims <- 5000
warmup <-1000
gibbs_chain <- matrix(0,ncol = 12,nrow = nsims - warmup)
param_names <-  c("BetaA0","BetaB0", "BetaC0","BetaA1","BetaB1","BetaC1",
                           "Alpha1", "Alpha0", "Kappa2", "Sigma2", "Tau2", "Phi")
colnames(gibbs_chain)<- param_names
nparams <- length(param_names)
sims <- mcmc_array(nsims - warmup, nchains, param_names)

# Initialize starting values for chain using randomly sampled measurements from data and the corresponding posterior estimates for sigma

# Initialize starting values for alpha as MLE estimates for log(lead) ~ f(distance to river), not controlling for soil type.  

n        <- length(y)
beta_fit <- lm(y ~ X - 1)
beta     <- coef(beta_fit)

# Assuming equal weight of deviance for fit of log lead concentration on error in estimation and error from spatial component.
sigma2   <- deviance(beta_fit) / (2*n)
tau2     <- deviance(beta_fit) / (2*n)

alpha_tau <- 10
beta_tau  <- 2

alpha_kappa <- 10
beta_kappa  <- 4

alpha_fit <- lm(beta ~ X_beta - 1)
kappa2    <- deviance(alpha_fit) / nrow(X_beta)
alpha_phi <- 10
phi       <- 1/rgamma(1,alpha_phi,alpha_phi)

# Flat prior on alpha
alpha_prior <- list(mean=rep(0,2),precision=rep(0,2))
H <- function(phi){
  return(exp(-D/phi))
}
phi_jumping <- function(phi_mn){
  phi <- rnorm(1,mean=phi_mn, sd=0.1)
  return(phi)
}
logposterior  <-  function(phi,sigma2,delta,beta,kappa2,tau2,alpha) {
  logpost <-0
  logposterior<- logpost - log(sqrt(sigma2^n)) + (-1/(2*sigma2))*crossprod(y-X %*% beta-delta) - log(sqrt(det(tau2*(H(phi))))) - (1/2) * t(delta) %*% solve(tau2 * H(phi)) %*% delta -
    log(sigma2)  - (alpha_phi+1)*log(phi) - (alpha_phi/phi) - log(sqrt(kappa2^6)) - (1/(2*kappa2)) * crossprod(beta- X_beta %*% alpha) 
   - (alpha_tau+1)*log(tau2) - (beta_tau/tau2) - (alpha_kappa+1)*log(kappa2) - (beta_kappa/kappa2)
       
  return(logposterior)
}
for (chain in 1:nchains) {
  gibbs_chain <- matrix(0,ncol = 12,nrow = nsims - warmup)
  for (it in 1:nsims) {
    # 1. Sample from posterior on alpha
    alpha <- bslm_sample1(beta, X_beta, sqrt(kappa2), alpha_prior)
    
    # 2. Sample from delta
    delta <- rnorm(n,mean=rep(0,n),sd = chol((tau2) * H(phi)) )
    
    # 3. Beta
    beta  <- bslm_sample1(y - delta, X, sqrt(sigma2),
                         list(mean = X_beta %*% alpha, precision = 1 / kappa2))

    # 4. Sigma2
    sigma2  <- (n * (1/n * crossprod(y - X %*% beta - delta))/rchisq(1,n))
    sigma2  <- as.vector(sigma2)
    # 5. Tau2
    nu <- alpha_tau + n/2
    s2 <- (2*beta_tau + t(delta) %*% solve(H(phi)) %*% delta)/(n+2*alpha_tau)
    tau2    <- (nu * (s2/rchisq(1,nu)))
    tau2    <- as.vector(tau2)
  #  tau2 <- 10
    # 6. Kappa2
    nAlpha <-6
    nu <- alpha_kappa + nAlpha/2
    s2 <- (2*beta_kappa+ crossprod(beta - X_beta %*% alpha))/(nAlpha+2*alpha_kappa)
    kappa2 <- (nu * (s2/rchisq(1,nu)))
    kappa2 <- as.vector(kappa2)
    
    # 7. Phi Random walk
    phi_star <- phi_jumping(phi)
    
    logR <- logposterior(phi_star,sigma2,delta,beta,kappa2,tau2,alpha) -          logposterior(phi,sigma2,delta,beta,kappa2,tau2,alpha)
     if (logR >= 0 || log(runif(1)) <= logR) {
          phi <- phi_star
     }
    
    if(it > warmup){
      sims[it - warmup, chain, ] <- c(beta,alpha,kappa2,sigma2,tau2,phi)
    }
    
  }
}
monitor(sims)
mcmc_trace(sims)
mcmc_acf(sims)
mcmc_dens_overlay(sims)
t(apply(sims[,1,,],2, function(x) quantile(x, c(.025,.25,.5,.75,.975))))

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiQmF5c2lhbiBEYXRhIEFuYWx5c2lzOiBGaW5hbCBQcm9qZWN0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiAKClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDbWQrU2hpZnQrRW50ZXIqLiAKYGBge3J9CgpsaWJyYXJ5KHJzdGFuKQpsaWJyYXJ5KGJheWVzcGxvdCkKbGlicmFyeShzcCkKZGF0YShtZXVzZSkKbGlicmFyeSgncGxvdGx5JykKbGlicmFyeShsYXR0aWNlKQpzb3VyY2UoIn4vRG9jdW1lbnRzL0JVXzIwMTlfRmFsbC9ic2xtLlIiKQpgYGAKCmBgYHtyfQpjb21wdXRlX2Rpc3RhbmNlcyA8LSBmdW5jdGlvbih4LHkpewogIG48LSBsZW5ndGgoeCkKICBEID0gbWF0cml4KDAsbnJvdz1uLG5jb2w9bikKICBmb3IoaSBpbiAxOm4pewogICAgZm9yKGogaW4gMTpuKXsKICAgICAgICBwMSA9IGMoeFtpXSx5W2ldKQogICAgICAgIHAyID0gYyh4W2pdLHlbal0pCiAgICAgICAgRFtpLGpdIDwtIHNxcnQoc3VtKChwMSAtIHAyKV4yKSkKICAgIH0KICB9CiAgcmV0dXJuKEQpCn0KCkQgPC0gY29tcHV0ZV9kaXN0YW5jZXMobWV1c2UkeCxtZXVzZSR5KQpwIDwtIHBsb3RfbHkoej1+RCkKbGF5b3V0KHAsdGl0bGUgPSAiRGlzdGFuY2VzIEJldHdlZW4gU2l0ZXMiLCB4YXhpcz1saXN0KHRpdGxlID0gJ1NpdGUnKSx5YXhpcz1saXN0KHRpdGxlID0gJ1NpdGUnKSkKCmBgYAoKYGBge3J9CgpwPC1wbG90X2x5KHg9IG1ldXNlJHgseT1tZXVzZSR5LHogPSB+bG9nKG1ldXNlJGxlYWQpKQpsYXlvdXQocCx0aXRsZSA9ICJMb2cgbGVhZCBjb25jZW50cmF0aW9uIGFzIGEgZnVuY3Rpb24gb2YgbG9jYXRpb24iLCBzY2VuZSA9IGxpc3QoeGF4aXM9bGlzdCh0aXRsZSA9ICd4IGxvY2F0aW9uJykseWF4aXM9bGlzdCh0aXRsZSA9ICd5IGxvY2F0aW9uJyksemF4aXM9bGlzdCh0aXRsZSA9ICdMb2cgbGVhZCcpKSkKCmBgYAoKRml4IHRhdTIgdG8gYmUgMSB0byB1bmRlcnN0YW5kIGltcGFjdCBvZiBwaGkuCmBgYHtyfQoKcGhpPTEKSCA8LSAxKmV4cCgtRC9waGkpCnAgPC0gcGxvdF9seSh6PX5IKQpsYXlvdXQocCx0aXRsZSA9ICJTcGF0aWFsIENvcnJlbGF0aW9uIGZvciBQaGkgPSAxIiwgeGF4aXM9bGlzdCh0aXRsZSA9ICdTaXRlJykseWF4aXM9bGlzdCh0aXRsZSA9ICdTaXRlJykpCgpwaGk9MzAwCkggPC0gMSpleHAoRC9waGkpCnAgPC0gcGxvdF9seSh6PX5IKQpsYXlvdXQocCx0aXRsZSA9ICJTcGF0aWFsIENvcnJlbGF0aW9uIGZvciBQaGkgPSAzMDAiLCB4YXhpcz1saXN0KHRpdGxlID0gJ1NpdGUnKSx5YXhpcz1saXN0KHRpdGxlID0gJ1NpdGUnKSkKCnBoaT0zMDAwCkggPC0gMSpleHAoLUQvcGhpKQpwIDwtIHBsb3RfbHkoej1+SCkKbGF5b3V0KHAsdGl0bGUgPSAiU3BhdGlhbCBDb3JyZWxhdGlvbiBmb3IgUGhpID0gMzAwMCIsIHhheGlzPWxpc3QodGl0bGUgPSAnU2l0ZScpLHlheGlzPWxpc3QodGl0bGUgPSAnU2l0ZScpKQpgYGAKCmBgYHtyfQoKeHlwbG90KGxvZyhsZWFkKSB+IGRpc3QubSB8IHNvaWwsIGRhdGEgPSBtZXVzZSwKICAgICAgIHBhbmVsID0gZnVuY3Rpb24oLi4uKSB7CiAgICAgICAgIHBhbmVsLnh5cGxvdCh0eXBlID0gInAiLCAuLi4pCiAgICAgICAgIHBhbmVsLmxtbGluZShsdHkgPSAyLCAuLi4pCiAgICAgICB9KQp4eXBsb3QobG9nKGxlYWQpIH4gZGlzdC5tICwgZGF0YSA9IG1ldXNlLAogICAgICAgcGFuZWwgPSBmdW5jdGlvbiguLi4pIHsKICAgICAgICAgcGFuZWwueHlwbG90KHR5cGUgPSAicCIsIC4uLikKICAgICAgICAgcGFuZWwubG1saW5lKGx0eSA9IDIsIC4uLikKICAgICAgIH0pCgpgYGAKClNldCB1cCBkZXNpZ24gbWF0cmljZXMKYGBge3J9CnkgPC0gbG9nKG1ldXNlJGxlYWQpClggPC0gbW9kZWwubWF0cml4KH4gLTEgKyBzb2lsICsgc29pbDpkaXN0Lm0sIGRhdGEgPSBtZXVzZSkKCkogPC0gbGVuZ3RoKGxldmVscyhtZXVzZSRzb2lsKSkKbiA8LSBucm93KFgpCnAgPC0gbmNvbChYKSAvIEoKc2l0ZV9qIDwtIGFnZ3JlZ2F0ZSguIH4gc29pbCwgZGF0YSA9IG1ldXNlLCBsZW5ndGgpCnNvaWxfc2l0ZSA8LSBkYXRhLmZyYW1lKGdyb3VwID0gc2l0ZV9qJHNvaWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZiA9IGMocmVwKCJfaW50ZXJjZXB0IiwgSiksIHJlcCgiX2Rpc3RhbmNlIiwgSikpKQpYX2JldGEgPC0gbW9kZWwubWF0cml4KH4gLTEgKyBjb2VmICwgZGF0YSA9IHNvaWxfc2l0ZSkKYGBgCgoKTWV0cm9wb2xpcy1HaWJicyBzYW1wbGluZyBwcm9jZWR1cmUKYGBge3J9Cm5jaGFpbnMgPC0gNApuc2ltcyA8LSA1MDAwCndhcm11cCA8LTEwMDAKZ2liYnNfY2hhaW4gPC0gbWF0cml4KDAsbmNvbCA9IDEyLG5yb3cgPSBuc2ltcyAtIHdhcm11cCkKcGFyYW1fbmFtZXMgPC0gIGMoIkJldGFBMCIsIkJldGFCMCIsICJCZXRhQzAiLCJCZXRhQTEiLCJCZXRhQjEiLCJCZXRhQzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQWxwaGExIiwgIkFscGhhMCIsICJLYXBwYTIiLCAiU2lnbWEyIiwgIlRhdTIiLCAiUGhpIikKY29sbmFtZXMoZ2liYnNfY2hhaW4pPC0gcGFyYW1fbmFtZXMKbnBhcmFtcyA8LSBsZW5ndGgocGFyYW1fbmFtZXMpCnNpbXMgPC0gbWNtY19hcnJheShuc2ltcyAtIHdhcm11cCwgbmNoYWlucywgcGFyYW1fbmFtZXMpCgojIEluaXRpYWxpemUgc3RhcnRpbmcgdmFsdWVzIGZvciBjaGFpbiB1c2luZyByYW5kb21seSBzYW1wbGVkIG1lYXN1cmVtZW50cyBmcm9tIGRhdGEgYW5kIHRoZSBjb3JyZXNwb25kaW5nIHBvc3RlcmlvciBlc3RpbWF0ZXMgZm9yIHNpZ21hCgojIEluaXRpYWxpemUgc3RhcnRpbmcgdmFsdWVzIGZvciBiZXRhIGFzIE1MRSBlc3RpbWF0ZXMgZm9yIGxvZyhsZWFkKSB+IGYoZGlzdGFuY2UgdG8gcml2ZXIpLCBub3QgY29udHJvbGxpbmcgZm9yIHNvaWwgdHlwZS4gIAoKbiAgICAgICAgPC0gbGVuZ3RoKHkpCmJldGFfZml0IDwtIGxtKHkgfiBYIC0gMSkKYmV0YSAgICAgPC0gY29lZihiZXRhX2ZpdCkKCiMgQXNzdW1pbmcgZXF1YWwgd2VpZ2h0IG9mIGRldmlhbmNlIGZvciBmaXQgb2YgbG9nIGxlYWQgY29uY2VudHJhdGlvbiBvbiBlcnJvciBpbiBlc3RpbWF0aW9uIGFuZCBlcnJvciBmcm9tIHNwYXRpYWwgY29tcG9uZW50LgpzaWdtYTIgICA8LSBkZXZpYW5jZShiZXRhX2ZpdCkgLyAoMipuKQp0YXUyICAgICA8LSBkZXZpYW5jZShiZXRhX2ZpdCkgLyAoMipuKQoKYWxwaGFfdGF1IDwtIDEwCmJldGFfdGF1ICA8LSAyCgphbHBoYV9rYXBwYSA8LSAxMApiZXRhX2thcHBhICA8LSA0CgphbHBoYV9maXQgPC0gbG0oYmV0YSB+IFhfYmV0YSAtIDEpCmthcHBhMiAgICA8LSBkZXZpYW5jZShhbHBoYV9maXQpIC8gbnJvdyhYX2JldGEpCmFscGhhX3BoaSA8LSAxMApwaGkgICAgICAgPC0gMS9yZ2FtbWEoMSxhbHBoYV9waGksYWxwaGFfcGhpKQoKIyBGbGF0IHByaW9yIG9uIGFscGhhCmFscGhhX3ByaW9yIDwtIGxpc3QobWVhbj1yZXAoMCwyKSxwcmVjaXNpb249cmVwKDAsMikpCmBgYAoKCmBgYHtyfQpIIDwtIGZ1bmN0aW9uKHBoaSl7CiAgcmV0dXJuKGV4cCgtRC9waGkpKQp9CmBgYAoKCmBgYHtyfQpwaGlfanVtcGluZyA8LSBmdW5jdGlvbihwaGlfbW4pewogIHBoaSA8LSBybm9ybSgxLG1lYW49cGhpX21uLCBzZD0wLjEpCiAgcmV0dXJuKHBoaSkKfQpgYGAKCmBgYHtyfQpsb2dwb3N0ZXJpb3IgIDwtICBmdW5jdGlvbihwaGksc2lnbWEyLGRlbHRhLGJldGEsa2FwcGEyLHRhdTIsYWxwaGEpIHsKICBsb2dwb3N0IDwtMAogIGxvZ3Bvc3RlcmlvcjwtIGxvZ3Bvc3QgLSBsb2coc3FydChzaWdtYTJebikpICsgKC0xLygyKnNpZ21hMikpKmNyb3NzcHJvZCh5LVggJSolIGJldGEtZGVsdGEpIC0gbG9nKHNxcnQoZGV0KHRhdTIqKEgocGhpKSkpKSkgLSAoMS8yKSAqIHQoZGVsdGEpICUqJSBzb2x2ZSh0YXUyICogSChwaGkpKSAlKiUgZGVsdGEgLQogICAgbG9nKHNpZ21hMikgIC0gKGFscGhhX3BoaSsxKSpsb2cocGhpKSAtIChhbHBoYV9waGkvcGhpKSAtIGxvZyhzcXJ0KGthcHBhMl42KSkgLSAoMS8oMiprYXBwYTIpKSAqIGNyb3NzcHJvZChiZXRhLSBYX2JldGEgJSolIGFscGhhKSAKICAgLSAoYWxwaGFfdGF1KzEpKmxvZyh0YXUyKSAtIChiZXRhX3RhdS90YXUyKSAtIChhbHBoYV9rYXBwYSsxKSpsb2coa2FwcGEyKSAtIChiZXRhX2thcHBhL2thcHBhMikKICAgICAgIAogIHJldHVybihsb2dwb3N0ZXJpb3IpCn0KYGBgCgpgYGB7cn0KZm9yIChjaGFpbiBpbiAxOm5jaGFpbnMpIHsKICBnaWJic19jaGFpbiA8LSBtYXRyaXgoMCxuY29sID0gMTIsbnJvdyA9IG5zaW1zIC0gd2FybXVwKQogIGZvciAoaXQgaW4gMTpuc2ltcykgewogICAgIyAxLiBTYW1wbGUgZnJvbSBwb3N0ZXJpb3Igb24gYWxwaGEKICAgIGFscGhhIDwtIGJzbG1fc2FtcGxlMShiZXRhLCBYX2JldGEsIHNxcnQoa2FwcGEyKSwgYWxwaGFfcHJpb3IpCiAgICAKICAgICMgMi4gU2FtcGxlIGZyb20gZGVsdGEKICAgIGRlbHRhIDwtIHJub3JtKG4sbWVhbj1yZXAoMCxuKSxzZCA9IGNob2woKHRhdTIpICogSChwaGkpKSApCiAgICAKICAgICMgMy4gQmV0YQogICAgYmV0YSAgPC0gYnNsbV9zYW1wbGUxKHkgLSBkZWx0YSwgWCwgc3FydChzaWdtYTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgbGlzdChtZWFuID0gWF9iZXRhICUqJSBhbHBoYSwgcHJlY2lzaW9uID0gMSAvIGthcHBhMikpCgogICAgIyA0LiBTaWdtYTIKICAgIHNpZ21hMiAgPC0gKG4gKiAoMS9uICogY3Jvc3Nwcm9kKHkgLSBYICUqJSBiZXRhIC0gZGVsdGEpKS9yY2hpc3EoMSxuKSkKICAgIHNpZ21hMiAgPC0gYXMudmVjdG9yKHNpZ21hMikKICAgICMgNS4gVGF1MgogICAgbnUgPC0gYWxwaGFfdGF1ICsgbi8yCiAgICBzMiA8LSAoMipiZXRhX3RhdSArIHQoZGVsdGEpICUqJSBzb2x2ZShIKHBoaSkpICUqJSBkZWx0YSkvKG4rMiphbHBoYV90YXUpCiAgICB0YXUyICAgIDwtIChudSAqIChzMi9yY2hpc3EoMSxudSkpKQogICAgdGF1MiAgICA8LSBhcy52ZWN0b3IodGF1MikKICAjICB0YXUyIDwtIDEwCiAgICAjIDYuIEthcHBhMgogICAgbkFscGhhIDwtNgogICAgbnUgPC0gYWxwaGFfa2FwcGEgKyBuQWxwaGEvMgogICAgczIgPC0gKDIqYmV0YV9rYXBwYSsgY3Jvc3Nwcm9kKGJldGEgLSBYX2JldGEgJSolIGFscGhhKSkvKG5BbHBoYSsyKmFscGhhX2thcHBhKQogICAga2FwcGEyIDwtIChudSAqIChzMi9yY2hpc3EoMSxudSkpKQogICAga2FwcGEyIDwtIGFzLnZlY3RvcihrYXBwYTIpCiAgICAKICAgICMgNy4gUGhpIFJhbmRvbSB3YWxrCiAgICBwaGlfc3RhciA8LSBwaGlfanVtcGluZyhwaGkpCiAgICAKICAgIGxvZ1IgPC0gbG9ncG9zdGVyaW9yKHBoaV9zdGFyLHNpZ21hMixkZWx0YSxiZXRhLGthcHBhMix0YXUyLGFscGhhKSAtICAgICAgICAgIGxvZ3Bvc3RlcmlvcihwaGksc2lnbWEyLGRlbHRhLGJldGEsa2FwcGEyLHRhdTIsYWxwaGEpCiAgICAgaWYgKGxvZ1IgPj0gMCB8fCBsb2cocnVuaWYoMSkpIDw9IGxvZ1IpIHsKICAgICAgICAgIHBoaSA8LSBwaGlfc3RhcgogICAgIH0KICAgIAogICAgaWYoaXQgPiB3YXJtdXApewogICAgICBzaW1zW2l0IC0gd2FybXVwLCBjaGFpbiwgXSA8LSBjKGJldGEsYWxwaGEsa2FwcGEyLHNpZ21hMix0YXUyLHBoaSkKICAgIH0KICAgIAogIH0KfQoKYGBgCgpgYGB7cn0KbW9uaXRvcihzaW1zKQptY21jX3RyYWNlKHNpbXMpCm1jbWNfYWNmKHNpbXMpCm1jbWNfZGVuc19vdmVybGF5KHNpbXMpCnQoYXBwbHkoc2ltc1ssMSwsXSwyLCBmdW5jdGlvbih4KSBxdWFudGlsZSh4LCBjKC4wMjUsLjI1LC41LC43NSwuOTc1KSkpKQpgYGAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDbWQrT3B0aW9uK0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDbWQrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCgo=